home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / docme.lha / doc.me / scanex.me < prev    next >
Text File  |  1992-09-25  |  44KB  |  1,608 lines

  1. .\" use: pic | tbl | eqn | ditroff -me
  2. .\"
  3. .\"    "@(#)bibmac.me    2.2    9/9/83";
  4. .de IP
  5. .ip \\$1 \\$2
  6. ..
  7. .de LP
  8. .lp
  9. ..
  10. .\"    @(#)bmac.std    2.2    9/9/83;
  11. .\" standard format troff commands
  12. .\" citation formatting strings
  13. .ds [[ [
  14. .ds ]] ]
  15. .ds ], ,\|
  16. .ds ]- -
  17. .ds [. " \&
  18. .ds .] .
  19. .ds [, " \&
  20. .ds ,] ,
  21. .ds [? " \&
  22. .ds ?] ?
  23. .ds [: " \&
  24. .ds :] :
  25. .ds [; " \&
  26. .ds ;] ;
  27. .ds [! " \&
  28. .ds !] !
  29. .ds [" " \&
  30. .ds "] \&"
  31. .ds [' " \&
  32. .ds '] '
  33. .ds [< " \&
  34. .ds >]
  35. .\" reference formmating strings
  36. .ds a] " \&
  37. .ds b] , \&
  38. .ds c] , \&
  39. .ds n] "\& and \&
  40. .ds m] "\& and \&
  41. .ds p] .
  42. .\" reference formmating macros
  43. .de s[   \" start reference
  44. .nh
  45. .IP [\\*([F] 5m
  46. ..
  47. .de e[   \" end reference
  48. .[-
  49. ..
  50. .de []   \" start to display collected references
  51. .LP
  52. ..
  53. .de ][   \" choose format
  54. .ie !"\\*([J"" \{\
  55. .    ie !"\\*([V"" .nr t[ 1    \" journal
  56. .    el            .nr t[ 5    \" conference paper
  57. .\}
  58. .el .ie !"\\*([B"" .nr t[ 3    \" article in book
  59. .el .ie !"\\*([R"" .nr t[ 4    \" technical report
  60. .el .ie !"\\*([I"" .nr t[ 2    \" book
  61. .el                .nr t[ 0    \" other
  62. .\\n(t[[
  63. ..
  64. .de 0[   \" other
  65. .s[
  66. .if !"\\*([A"" \\*([A\\c
  67. .if !"\\*([T"" , \\*([T\\c
  68. .if !"\\*([V"" , Vol. \\*([V\\c
  69. .if !"\\*([O"" , \\*([O\\c
  70. .if !"\\*([D"" , \\*([D\\c
  71. \&.
  72. .e[
  73. ..
  74. .de 1[ \" journal article
  75. .s[
  76. .if !"\\*([A"" \\*([A,
  77. .if !"\\*([T""  \\*([T,
  78. \\fI\\*([J \\*([V\\fP\c
  79. .if !"\\*([N"" ,\\*([N
  80. .if !"\\*([D"" (\\*([D)\c
  81. .if !"\\*([P"" , \\*([P\c
  82. .if !"\\*([I"" , \\*([I\c
  83. \\&.
  84. .if !"\\*([O"" \\*([O.
  85. .e[
  86. ..
  87. .de 2[ \" book
  88. .s[
  89. .ie !"\\*([A"" \\*([A,
  90. .el .if !"\\*([E"" \{\
  91. .       ie \\n([E-1 \\*([E, eds.,
  92. .       el \\*([E, ed.,\}
  93. .if !"\\*([T"" \\fI\\*([T\\fP,
  94. .rm a[
  95. .if !"\\*([I"" .ds a[ \\*([I
  96. .if !"\\*([C"" \{\
  97. .       if !"\\*(a["" .as a[ , \\&
  98. .       as a[ \\*([C\}
  99. .if !"\\*([D"" \{\
  100. .       if !"\\*(a["" .as a[ , \\&
  101. .       as a[ \\*([D\}
  102. \\*(a[.
  103. .if !"\\*([G"" Gov. ordering no. \\*([G.
  104. .if !"\\*([O"" \\*([O.
  105. .e[
  106. ..
  107. .de 3[ \" article in book
  108. .s[
  109. .if !"\\*([A"" \\*([A,
  110. .if !"\\*([T"" \\*([T,
  111. in \\fI\\*([B\\fP\c
  112. .if !"\\*([V"" , vol. \\*([V
  113. .if !~\\*([E~~ \{\
  114. .       ie , \\n([E-1  \\*([E (editors)\c
  115. .       el , \\*([E (editor)\c\}
  116. .if !"\\*([I"" , \\*([I\c
  117. .if !"\\*([C"" , \\*([C\c
  118. .if !"\\*([D"" , \\*([D\c
  119. .if !"\\*([P"" , \\*([P\c
  120. \\&.
  121. .if !"\\*([O"" \\*([O.
  122. .e[
  123. ..
  124. .de 4[ \" report
  125. .s[
  126. .if !"\\*([A"" \\*([A,
  127. .if !~\\*([E~~ \{\
  128. .       ie \\n([E-1 \\*([E, editors.
  129. .       el \\*([E, editor.\}
  130. \\*([T,
  131. \\*([R\c
  132. .if !"\\*([G"" \& (\\*([G)\c
  133. .if !"\\*([I"" , \\*([I\c
  134. .if !"\\*([C"" , \\*([C\c
  135. .if !"\\*([D"" , \\*([D\c
  136. \\&.
  137. .if !"\\*([O"" \\*([O.
  138. .e[
  139. ..
  140. .de 5[ \" conference paper
  141. .s[
  142. .if !"\\*([A"" \\*([A,
  143. .if !"\\*([T"" \\*([T,
  144. \\fI\\*([J\\fP,
  145. .if !"\\*([C"" \\*([C,
  146. .if !"\\*([D"" \\*([D\c
  147. .if !"\\*([P"" , \\*([P\c
  148. \\&.
  149. .if !"\\*([O"" \\*([O.
  150. .e[
  151. ..
  152. .de [-   \" clean up after yourself
  153. .rm [A [B [C [D
  154. .rm [E [F [G
  155. .rm [I [J [K
  156. .rm [N [O [P
  157. .rm [R [T
  158. .rm [V [W
  159. ..
  160. .\"    @(#)bmac.std    2.2    8/24/83;
  161. .\" standard format troff commands
  162. .\" citation formatting strings
  163. .ds [[ [
  164. .ds ]] ]
  165. .ds ], ,\|
  166. .ds ]- -
  167. .ds [. " \&
  168. .ds .] .
  169. .ds [, " \&
  170. .ds ,] ,
  171. .ds [< " \&
  172. .ds >]
  173. .\" reference formmating strings
  174. .ds c] , \&
  175. .ds n] "" and \&
  176. .ds m] "" and \&
  177. .ds a] " \&
  178. .\" reference formmating macros
  179. .de s[   \" start reference
  180. .nh
  181. .IP [\\*([F] 5m
  182. ..
  183. .de e[   \" end reference
  184. .[-
  185. ..
  186. .de []   \" start to display collected references
  187. .SH
  188. References
  189. .LP
  190. ..
  191. .de ][   \" choose format
  192. .ie !"\\*([J"" \{\
  193. .    ie !"\\*([V"" .nr t[ 1    \" journal
  194. .    el            .nr t[ 5    \" conference paper
  195. .\}
  196. .el .ie !"\\*([B"" .nr t[ 3    \" article in book
  197. .el .ie !"\\*([R"" .nr t[ 4    \" technical report
  198. .el .ie !"\\*([I"" .nr t[ 2    \" book
  199. .el                .nr t[ 0    \" other
  200. .\\n(t[[
  201. ..
  202. .de 0[   \" other
  203. .s[
  204. .if !"\\*([A"" \\*([A,
  205. .if !"\\*([T"" \\*([T,
  206. .if !"\\*([O"" \\*([O\c
  207. .if !"\\*([D"" , \\*([D\c
  208. \&.
  209. .e[
  210. ..
  211. .de 1[ \" journal article
  212. .s[
  213. .if !"\\*([A"" \\*([A,
  214. .if !"\\*([T"" \\*([T,
  215. \\fI\\*([J \\*([V\\fP,
  216. .if !"\\*([N"" \\*([N
  217. .if !"\\*([D"" (\\*([D),
  218. .if !"\\*([P"" \\*([P\c
  219. .if !"\\*([I"" , \\*([I\c
  220. \\&.
  221. .if !"\\*([O"" \\*([O.
  222. .e[
  223. ..
  224. .de 2[ \" book
  225. .s[
  226. .ie !"\\*([A"" \\*([A,
  227. .el .if !"\\*([E"" \{\
  228. .       ie \\n([E-1 \\*([E, eds.,
  229. .       el \\*([E, ed.,\}
  230. .if !"\\*([T"" \\fI\\*([T\\fP,
  231. .rm a[
  232. .if !"\\*([I"" .ds a[ \\*([I
  233. .if !"\\*([C"" \{\
  234. .       if !"\\*(a["" .as a[ , \\&
  235. .       as a[ \\*([C\}
  236. .if !"\\*([D"" \{\
  237. .       if !"\\*(a["" .as a[ , \\&
  238. .       as a[ \\*([D\}
  239. \\*(a[.
  240. .if !"\\*([G"" Gov. ordering no. \\*([G.
  241. .if !"\\*([O"" \\*([O.
  242. .e[
  243. ..
  244. .de 3[ \" article in book
  245. .s[
  246. .if !"\\*([A"" \\*([A,
  247. .if !"\\*([T"" \\*([T,
  248. in \\fI\\*([B\\fP,
  249. .if !"\\*([V"" vol. \\*([V,
  250. .if !"\\*([E"" \\*([E (ed.),
  251. .if !"\\*([I"" \\*([I,
  252. .if !"\\*([C"" \\*([C,
  253. .if !"\\*([D"" \\*([D\c
  254. .if !"\\*([P"" , \\*([P\c
  255. \\&.
  256. .if !"\\*([O"" \\*([O.
  257. .e[
  258. ..
  259. .de 4[ \" report
  260. .s[
  261. .if !"\\*([A"" \\*([A,
  262. \\*([T,
  263. \\*([R\c
  264. .if !"\\*([G"" \& (\\*([G)\c
  265. .if !"\\*([I"" , \\*([I\c
  266. .if !"\\*([C"" , \\*([C\c
  267. .if !"\\*([D"" , \\*([D\c
  268. \\&.
  269. .if !"\\*([O"" , \\*([O.
  270. .e[
  271. ..
  272. .de 5[ \" conference paper
  273. .s[
  274. .if !"\\*([A"" \\*([A,
  275. .if !"\\*([T"" \\*([T,
  276. \\fI\\*([J\\fP,
  277. .if !"\\*([C"" \\*([C\c
  278. .if !"\\*([D"" , \\*([D\c
  279. .if !"\\*([P"" , \\*([P\c
  280. \\&.
  281. .if !"\\*([O"" , \\*([O.
  282. .e[
  283. ..
  284. .de [-   \" clean up after yourself
  285. .rm [A [B [C [D
  286. .rm [E [F [G
  287. .rm [I [J [K
  288. .rm [N [O [P
  289. .rm [R [T
  290. .rm [V [W
  291. ..
  292. .if t \{ \
  293. .pl 29.7c    \" page length
  294. .po 2.5c    \" page offset (left margin)
  295. .ll 16.5c    \" line length
  296. .lt 16.5c    \" title length
  297. .nr LL 16.5c
  298. .nr )l 29.7c
  299. .nr hm 2c
  300. .nr $r 9    \" factor for vertical spacing
  301. .nr $R \n($r
  302. .sz 12        \" font size
  303. .nr pp 12
  304. .nr sp 12
  305. .nr tp 12
  306. .nr fp 10
  307. .hc ~        \" hyphenation character
  308. .        \" Umlauts and sharp s
  309. .ds A \(A:
  310. .ds O \(O:
  311. .ds U \(U:
  312. .ds a \(a:
  313. .ds o \(o:
  314. .ds u \(u:
  315. .ds s \(ss
  316. .        \"  UMLAUT  \*:u, etc.
  317. .ds : \v'-0.6m'\h'(1u-(\\n(.fu%2u))*0.13m+0.06m'\z.\h'0.2m'\z.\h'-((1u-(\\n(.fu%2u))*0.13m+0.26m)'\v'0.6m'
  318. .\}
  319. .if n \{ \
  320. .po 0        \" page offset (left margin)
  321. .ll 78        \" line length
  322. .lt 78        \" title length
  323. .nr $r 4    \" factor for vertical spacing
  324. .nr $R \n($r
  325. .hc ~        \" hyphenation character
  326. .        \" Umlaute und scharfes s
  327. .ds A Ae
  328. .ds O Oe
  329. .ds U Ue
  330. .ds a ae
  331. .ds o oe
  332. .ds u ue
  333. .ds s sz
  334. .\}
  335. .de _
  336. \&\\$1\l'|0\(ul'\\$2
  337. ..
  338. .de FT        \" font for programs
  339. .ft C
  340. .sz -2
  341. ..
  342. .de FR
  343. .ft R
  344. .sz +2
  345. ..
  346. .de []        \" start to display collected references
  347. .uh References
  348. .lp
  349. ..
  350. .de $0        \" collect table of contents
  351. .(x
  352. .ta 2c
  353. .ie '\\$2''    \\$1
  354. .el \\$2.    \\$1
  355. .)x
  356. ..
  357. .de np
  358. .nr $p +1
  359. .ip \\n($p.
  360. ..
  361. .de SH
  362. .sp 0.5
  363. .in -3
  364. .r \\$1
  365. .sp 0.5
  366. .in +3
  367. ..
  368. .de PP
  369. .sp 0.5
  370. ..
  371. .de IP
  372. .ip \\$1 \\$2
  373. ..
  374. .de I
  375. .i \\$1
  376. ..
  377. .de TH
  378. ..
  379. .hc @
  380. .EQ
  381. gsize 12
  382. delim $$
  383. .EN
  384. .b " "
  385. .sp 1c
  386. .ta 9c
  387. .ft R
  388. .sz 12
  389. \l'17.1c'
  390. .nf
  391.  
  392.  
  393.     Selected Examples of
  394.     Scanner Specifications
  395.  
  396.     J. Grosch
  397.  
  398.  
  399. \l'17.1c'
  400. .sp 12.5c
  401. \l'17.1c'
  402. .ft H
  403. .nf
  404.     GESELLSCHAFT F\*UR MATHEMATIK
  405.     UND DATENVERARBEITUNG MBH
  406.  
  407.     FORSCHUNGSSTELLE F\*UR
  408.     PROGRAMMSTRUKTUREN
  409.     AN DER UNIVERSIT\*AT KARLSRUHE
  410. .r
  411. \l'17.1c'
  412. .bp
  413. .oh ''Scanner Specification'%'
  414. .eh ''Scanner Specification'%'
  415. .ce 99
  416. .sz 20
  417. .b " "
  418. .sp 2
  419. Project
  420. .sp
  421. .b "Compiler Generation"
  422. .sp
  423. .sz 12
  424. \l'15c'
  425. .sp
  426. .sz 16
  427. .b "Selected Examples of Scanner Specifications"
  428. .sp 2
  429. Josef Grosch
  430. .sp 2
  431. .sz 14
  432. Mar. 8, 1988
  433. .sp
  434. .sz 12
  435. \l'15c'
  436. .sp 2
  437. Report No. 7
  438. .sp 2
  439. Copyright \(co 1988 GMD
  440. .sp 2
  441. Gesellschaft f\*ur Mathematik und Datenverarbeitung mbH
  442. Forschungsstelle an der Universit\*at Karlsruhe
  443. Vincenz-Prie\*snitz-Str. 1
  444. D-7500 Karlsruhe
  445. .ce 0
  446. .fi
  447. .bp 2
  448. .sh 1 Introduction
  449. .pp
  450. Among the tokens to be recognized by scanners are a few that require non
  451. trivial processing: comments, strings, and character constants.
  452. Even identifiers and keywords may cause some trouble if the language defines
  453. upper-case and lower-case letters to have the same meaning.
  454. The problems with these tokens are the following:
  455. .ip -
  456. maintaining the line count during tokens extending on several lines
  457. .ip -
  458. maintaining the column count during tokens containing tab characters
  459. .ip -
  460. computation of the source position of tokens extending on several lines or
  461. of compound tokens which are recognized as a sequence of subtokens
  462. .ip -
  463. nested comments
  464. .ip -
  465. report unclosed strings and comments as errors
  466. .ip -
  467. computing the internal representation of strings
  468. .ip -
  469. conversion of escape sequences such as doubled string delimiters or
  470. preceding escape characters
  471. .ip -
  472. normalization of upper-case and lower-case letters
  473. .lp
  474. The following chapters contain solutions to the above problems for the
  475. languages Pascal, Modula, C, and Ada. The solutions are scanner specifications
  476. suitable as input for the scanner generator Rex\*([<\*([[Gro87\*(]]\*(>].
  477. The primary intention of this paper is to serve as a reference manual
  478. containing examples for non trivial cases.
  479. All specifications use C as target language except the chapter on Modula
  480. which uses Modula.
  481. The Appendix contains a complete scanner specification for Ada with Modula
  482. as target language.
  483. .sh 1 Pascal
  484. .pp
  485. .sh 2 Comments
  486. .lp
  487. Problems to solve:
  488. .ip -
  489. unclosed comments
  490. .ip -
  491. newline characters
  492. .ip -
  493. tab characters
  494. .lp
  495. .(b L
  496. Solution:
  497. .sp 0.5
  498. .FT
  499. EOF     {IF yyStartState = Comment THEN Error ("unclosed comment"); END;}
  500.  
  501. DEFINE  CmtCh   = - {*\\\\}\\\\t\\\\n}.
  502.  
  503. START   Comment
  504.  
  505. RULE
  506.  
  507.            "(*" | "{"     :- {yyStart (Comment);}
  508. #Comment#  "*)" | "}"     :- {yyStart (STD);}
  509. #Comment#  "*"  | CmtCh + :- {}
  510. .)b
  511. .pp
  512. Comments are processed in a separate start state called
  513. .i Comment.
  514. Everything is skipped in this state except closing comment
  515. brackets which switch back to start state STD.
  516. The single characters '*' or '}'
  517. which can start a closing comment bracket have to be skipped
  518. separately. Otherwise closing comment brackets would not be
  519. recognized because of the "longest match" rule of Rex.
  520. An unclosed comment is indicated by reaching end of file while in start state
  521. .i Comment.
  522. We presuppose the existence of a procedure
  523. .i Error
  524. to report this condition.
  525. We don't need to care about tab and newline characters other than excluding
  526. them from the set
  527. .i CmtCh
  528. because the two rules needed for this problem are already predefined by
  529. Rex:
  530. .lp
  531. .(b L
  532. .FT
  533. #Comment#  \\\\t :- {yyTab;}
  534. #Comment#  \\\\n :- {yyEol (0);}
  535. .)b
  536. .sh 2 Identifiers
  537. .lp
  538. Problems to solve:
  539. .ip -
  540. normalization of upper-case and lower-case letters
  541. .lp
  542. .(b L
  543. Solution:
  544. .sp 0.5
  545. .FT
  546. EXPORT  {
  547. # include "Idents.h"
  548. # include "Positions.h"
  549. typedef struct {
  550.    tPosition Position;
  551.    tIdent    Ident;
  552. } tScanAttribute;
  553. extern void ErrorAttribute ();
  554. }
  555.  
  556. GLOBAL  {
  557. # define TokIdentifier ...
  558. void ErrorAttribute (Token, Attribute)
  559.    int Token;
  560.    tScanAttribute * Attribute;
  561.    {
  562.       Attribute->Ident = NoIdent;
  563.    }
  564. }
  565.  
  566. LOCAL   {char String [256]; int L;}
  567.  
  568. DEFINE  letter  = {A-Z a-z}.
  569.         digit   = {0-9}.
  570.  
  571. RULE
  572.  
  573. letter (letter | digit) * : {L = GetLower (String);
  574.                 Attribute.Ident = MakeIdent (String, L); return TokIdentifier;}
  575. .)b
  576. .pp
  577. Normalization of upper-case and lower-case letters to lower-case is done by the
  578. predefined operation
  579. .i GetLower
  580. of Rex.
  581. .bp
  582. .sh 2 "Character Constants"
  583. .lp
  584. Problems to solve:
  585. .ip -
  586. conversion
  587. .ip -
  588. tab characters
  589. .lp
  590. .(b L
  591. Solution:
  592. .sp 0.5
  593. .FT
  594. EXPORT  {
  595. # include "Positions.h"
  596. typedef struct {
  597.    tPosition Position;
  598.    char      Char;
  599. } tScanAttribute;
  600. extern void ErrorAttribute ();
  601. }
  602.  
  603. GLOBAL  {
  604. # define TokCharConst ...
  605. void ErrorAttribute (Token, Attribute)
  606.    int Token;
  607.    tScanAttribute * Attribute;
  608.    {
  609.       Attribute->Char = '\\\\0';
  610.    }
  611. }
  612.  
  613. RULE
  614.  
  615. \&''''    : {Attribute.Char = '\\\\''; return TokCharConst;}
  616. \&' \\\\t '  : {Attribute.Char = '\\\\t'; yyTab2 (1, 1); return TokCharConst;}
  617. \&' ANY ' : {Attribute.Char = TokenPtr [1]; return TokCharConst;}
  618. .)b
  619. .pp
  620. In this example the order of the rules is significant because the last rule
  621. would also match the characters of the preceding one.
  622. .bp
  623. .sh 2 "Strings"
  624. .lp
  625. Problems to solve:
  626. .ip -
  627. conversion
  628. .ip -
  629. doubled delimiters
  630. .ip -
  631. tab characters
  632. .ip -
  633. unclosed strings (at end of lines)
  634. .ip -
  635. source position
  636. .lp
  637. .(b L
  638. Solution:
  639. .sp 0.5
  640. .FT
  641. EXPORT  {
  642. # include "StringMem.h"
  643. # include "Positions.h"
  644. typedef struct {
  645.    tPosition  Position;
  646.    tStringRef StringRef;
  647. } tScanAttribute;
  648. extern void ErrorAttribute ();
  649. }
  650.  
  651. GLOBAL  {
  652. # define TokString ...
  653. void ErrorAttribute (Token, Attribute) ...
  654. }
  655.  
  656. LOCAL   {char String [256]; int L;}
  657.  
  658. DEFINE  StrCh   = - {'\\\\t\\\\n}.
  659.  
  660. START   string
  661.  
  662. RULE
  663.  
  664. #STD#    '      :  {yyStart (string); L = 0;}
  665. #string# StrCh +:- {L += GetWord (& String [L]);}
  666. #string# ''     :- {String [L ++] = '\\\\'';}
  667. #string# '      :- {yyStart (STD); String [L] = '\\\\0';
  668.                     Attribute.StringRef = PutString (String, L);
  669.                     return TokString;}
  670. #string# \\\\t     :- {String [L ++] = '\\\\t'; yyTab;}
  671. #string# \\\\n     :- {Error ("unclosed string"); yyEol (0);
  672.                     yyStart (STD); String [L] = '\\\\0';
  673.                     Attribute.StringRef = PutString (String, L);
  674.                     return TokString;}
  675. .)b
  676. .pp
  677. We presuppose the existence of a string memory module
  678. .i StringMem.
  679. The procedure
  680. .i PutString
  681. stores a string in the string memory and returns a reference to it which can
  682. be used as attribute of the token
  683. .i TokString.
  684. .bp
  685. .sh 2 "Keywords"
  686. .lp
  687. Problems to solve:
  688. .ip -
  689. normalization of upper-case and lower-case letters
  690. .lp
  691. .(b L
  692. Solution:
  693. .sp 0.5
  694. .FT
  695. GLOBAL  {
  696. # define TokAND       ...
  697.    ...
  698. # define TokWITH         ...
  699. void ErrorAttribute (Token, Attribute) ...
  700. }
  701.  
  702. DEFINE  A = {Aa}.
  703.           ...
  704.         Z = {Zz}.
  705.  
  706. RULE
  707.  
  708. A N D           : {return TokAND       ;}
  709.   ...
  710. W I T H         : {return TokWITH      ;}
  711. .)b
  712. .pp
  713. The idea of the solution is to define identifiers A to Z to stand for the
  714. corresponding upper-case as well as lower-case letters. Then specifying the
  715. keywords in upper-case and spaced does the job.
  716. .bp
  717. .sh 1 Modula
  718. .pp
  719. .sh 2 Comments
  720. .lp
  721. Problems to solve:
  722. .ip -
  723. nested comments
  724. .ip -
  725. unclosed comments
  726. .ip -
  727. newline characters
  728. .ip -
  729. tab characters
  730. .lp
  731. .(b L
  732. Solution:
  733. .sp 0.5
  734. .FT
  735. GLOBAL  {VAR NestingLevel: CARDINAL;}
  736.  
  737. BEGIN   {NestingLevel := 0;}
  738.  
  739. EOF     {IF yyStartState = Comment THEN Error ("unclosed comment"); END;}
  740.  
  741. DEFINE  CmtCh   = - {*(\\\\t\\\\n}.
  742.  
  743. START   Comment
  744.  
  745. RULE
  746.  
  747. #STD, Comment# "(*" :- {INC (NestingLevel); yyStart (Comment);}
  748. #Comment#  "*)" :- {DEC (NestingLevel);
  749.                     IF NestingLevel = 0 THEN yyStart (STD); END;}
  750. #Comment#  "(" | "*" | CmtCh + :- {}
  751. .)b
  752. .pp
  753. We need a variable
  754. .i NestingLevel
  755. to count the nesting depth of comments because it is not possible to specify
  756. nested comments by a regular expression. Comments are processed in a separate
  757. start state called
  758. .i Comment.
  759. Everything is skipped in this state except opening or closing comment
  760. brackets which
  761. trigger a change of the nesting level. The single characters '(' and '*'
  762. which can start opening or closing comment brackets have to be skipped
  763. separately. Otherwise comment brackets within comment would not be
  764. recognized because of the "longest match" rule of Rex.
  765. An unclosed comment is indicated by reaching end of file while in start state
  766. .i Comment.
  767. We presuppose the existence of a procedure
  768. .i Error
  769. to report this condition.
  770. We don't need to care about tab and newline characters other than excluding
  771. them from the set
  772. .i CmtCh
  773. because the two rules needed for this problem are already predefined by
  774. Rex:
  775. .lp
  776. .(b L
  777. .FT
  778. #Comment#  \\\\t :- {yyTab;}
  779. #Comment#  \\\\n :- {yyEol (0);}
  780. .)b
  781. .bp
  782. .sh 2 Strings
  783. .lp
  784. Problems to solve:
  785. .ip -
  786. conversion
  787. .ip -
  788. tab characters
  789. .ip -
  790. unclosed strings (at end of lines)
  791. .ip -
  792. source position
  793. .lp
  794. .(b L
  795. Solution:
  796. .sp 0.5
  797. .FT
  798. EXPORT  {
  799.    FROM StringMem IMPORT tStringRef;
  800.    FROM Positions IMPORT tPosition;
  801.    TYPE tScanAttribute = RECORD
  802.       Position  : tPosition;
  803.       StringRef : tStringRef;
  804.    END;
  805.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  806. }
  807.  
  808. GLOBAL  {
  809.    FROM Strings     IMPORT tString, AssignEmpty, Concatenate, Append;
  810.    FROM StringMem   IMPORT PutString;
  811.  
  812.    CONST TokString = ...;
  813.  
  814.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  815.       BEGIN Attribute.StringRef := ...; END ErrorAttribute;
  816. }
  817.  
  818. LOCAL   {VAR String, S: tString;}
  819.  
  820. DEFINE  StrCh1  = - {'\\\\t\\\\n}.
  821.         StrCh2  = - {"\\\\t\\\\n}.
  822.  
  823. START   Str1, Str2
  824.  
  825. RULE
  826.  
  827. #STD#   '       :  {AssignEmpty (String); yyStart (Str1);}
  828. #Str1#  StrCh1+ :- {GetWord (S); Concatenate (String, S);}
  829. #Str1#  '       :- {yyStart (STD);
  830.                     Attribute.StringRef := PutString (String);
  831.                     RETURN TokString;}
  832. .sp 0.5
  833. #STD#   \\\\"      :  {AssignEmpty (String); yyStart (Str2);}
  834. #Str2#  StrCh2+ :- {GetWord (S); Concatenate (String, S);}
  835. #Str2#  \\\\"      :- {yyStart (STD);
  836.                     Attribute.StringRef := PutString (String);
  837.                     RETURN TokString;}
  838. .sp 0.5
  839. #Str1, Str2# \\\\t :- {Append (String, 11C); yyTab;}
  840. #Str1, Str2# \\\\n :- {Error ("unclosed string"); yyEol (0); yyStart (STD);
  841.                     Attribute.StringRef := PutString (String);
  842.                     RETURN TokString;}
  843. .)b
  844. .pp
  845. Again two separate start states are used to recognize the two forms of
  846. Modula-2 strings. We presuppose the existence of a string handling module
  847. .i Strings
  848. and a string memory module
  849. .i StringMem.
  850. The procedure
  851. .i PutString
  852. stores a string in the string memory and returns a reference to it which can
  853. be used as attribute of the token
  854. .i TokString.
  855. .bp
  856. .sh 1 C
  857. .pp
  858. .sh 2 Comments
  859. .lp
  860. Problems to solve:
  861. .ip -
  862. unclosed comments
  863. .ip -
  864. newline characters
  865. .ip -
  866. tab characters
  867. .lp
  868. .(b L
  869. Solution:
  870. .sp 0.5
  871. .FT
  872. EOF     {if (yyStartState == Comment) Error ("unclosed comment");}
  873.  
  874. DEFINE  CmtCh   = - {*\\\\t\\\\n}.
  875.  
  876. START   Comment
  877.  
  878. RULE
  879.  
  880.            "/*" :- {yyStart (Comment);}
  881. #Comment#  "*/" :- {yyStart (STD);}
  882. #Comment#  "*" | CmtCh + :- {}
  883. .)b
  884. .pp
  885. Comments are processed in a separate start state called
  886. .i Comment.
  887. Everything is skipped in this state except closing comment
  888. brackets which switch back to start state STD.
  889. The single character '*'
  890. which can start a closing comment bracket has to be skipped
  891. separately. Otherwise closing comment brackets would not be
  892. recognized because of the "longest match" rule of Rex.
  893. An unclosed comment is indicated by reaching end of file while in start state
  894. .i Comment.
  895. We presuppose the existence of a procedure
  896. .i Error
  897. to report this condition.
  898. We don't need to care about tab and newline characters other than excluding
  899. them from the set
  900. .i CmtCh
  901. because the two rules needed for this problem are already predefined by
  902. Rex:
  903. .lp
  904. .(b L
  905. .FT
  906. #Comment#  \\\\t :- {yyTab;}
  907. #Comment#  \\\\n :- {yyEol (0);}
  908. .)b
  909. .bp
  910. .sh 2 "Character Constants"
  911. .lp
  912. Problems to solve:
  913. .ip -
  914. conversion
  915. .ip -
  916. escape sequences
  917. .ip -
  918. tab characters
  919. .lp
  920. .(b L
  921. Solution:
  922. .sp 0.5
  923. .FT
  924. EXPORT  {
  925. # include "Positions.h"
  926. typedef struct {
  927.    tPosition Position;
  928.    char      Char;
  929. } tScanAttribute;
  930. extern void ErrorAttribute ();
  931. }
  932.  
  933. GLOBAL  {
  934. # define TokChar ...
  935. void ErrorAttribute (Token, Attribute)
  936.    int Token;
  937.    tScanAttribute * Attribute;
  938.    {
  939.       Attribute->Char = '\\\\0';
  940.    }
  941. }
  942.  
  943. LOCAL   {char String [256];}
  944.  
  945. RULE
  946.  
  947. \&' \\\\t '        : {Attribute.Char = '\\\\t'; yyTab2 (1, 1); return TokChar;}
  948. \&' ANY '       : {Attribute.Char = TokenPtr [1]; return TokChar;}
  949. \&' \\\\\\\\ n '      : {Attribute.Char = '\\\\n'; return TokChar;}
  950. \&' \\\\\\\\ t '      : {Attribute.Char = '\\\\t'; return TokChar;}
  951. \&' \\\\\\\\ v '      : {Attribute.Char = '\\\\v'; return TokChar;}
  952. \&' \\\\\\\\ b '      : {Attribute.Char = '\\\\b'; return TokChar;}
  953. \&' \\\\\\\\ r '      : {Attribute.Char = '\\\\r'; return TokChar;}
  954. \&' \\\\\\\\ f '      : {Attribute.Char = '\\\\f'; return TokChar;}
  955. \&' \\\\\\\\ {0-7}[1-3] ' : {(void) GetWord (String);
  956.                  sscanf (String + 2, "%o", & Attribute.Char);
  957.                  return TokChar;}
  958. \&' \\\\\\\\ ANY '    : {Attribute.Char = TokenPtr [2]; return TokChar;}
  959. .)b
  960. .pp
  961. In this example the order of the rules is significant because the second rule
  962. would also match the characters of the first one. The same holds for the
  963. group of following rules with respect to the last rule.
  964. .bp
  965. .sh 2 Strings
  966. .lp
  967. Problems to solve:
  968. .ip -
  969. conversion
  970. .ip -
  971. escape sequences
  972. .ip -
  973. tab characters
  974. .ip -
  975. strings ranging over several lines
  976. .ip -
  977. source position
  978. .lp
  979. .(b L
  980. Solution:
  981. .sp 0.5
  982. .FT
  983. EXPORT  {
  984. # include "StringMem.h"
  985. # include "Positions.h"
  986. typedef struct {
  987.    tPosition  Position;
  988.    tStringRef StringRef;
  989. } tScanAttribute;
  990. extern void ErrorAttribute ();
  991. }
  992.  
  993. GLOBAL  {
  994. # define TokString ...
  995. void ErrorAttribute (Token, Attribute) ...
  996. }
  997.  
  998. LOCAL   {char String [256], S [5]; int L;}
  999.  
  1000. DEFINE  StrCh   = - {"\\\\t\\\\n\\\\\\\\}.
  1001.  
  1002. START   string
  1003.  
  1004. RULE
  1005.  
  1006. #STD#    \\\\"     :  {yyStart (string); L = 0;}
  1007. #string# StrCh+ :- {L += GetWord (& String [L]);}
  1008. #string# \\\\t     :- {String [L ++] = '\\\\t'); yyTab;}
  1009. #string# \\\\\\\\ n   :- {String [L ++] = '\\\\n');}
  1010. #string# \\\\\\\\ t   :- {String [L ++] = '\\\\t');}
  1011. #string# \\\\\\\\ v   :- {String [L ++] = '\\\\v');}
  1012. #string# \\\\\\\\ b   :- {String [L ++] = '\\\\b');}
  1013. #string# \\\\\\\\ r   :- {String [L ++] = '\\\\r');}
  1014. #string# \\\\\\\\ f   :- {String [L ++] = '\\\\f');}
  1015. #string# \\\\\\\\ {0-7}[1-3] :- {(void) GetWord (S);
  1016.                     sscanf (S + 1, "%o", & String [L ++]);}
  1017. #string# \\\\\\\\ ANY :- {(void) GetWord (S); String [L ++] = S [1];}
  1018. #string# \\\\\\\\ \\\\n  :- {yyEol (0); String [L ++] = '\\\\n';}
  1019. #string# \\\\"     :- {yyStart (STD); String [L] = '\\\\0';
  1020.                     Attribute.StringRef = PutString (String, L);
  1021.                     return TokString;}
  1022. #string# \\\\n     :- {Error ("unclosed string"); yyEol (0);
  1023.                     yyStart (STD); String [L] = '\\\\0';
  1024.                     Attribute.StringRef = PutString (String, L);
  1025.                     return TokString;}
  1026. .)b
  1027. .pp
  1028. We presuppose the existence of a string memory module
  1029. .i StringMem.
  1030. The procedure
  1031. .i PutString
  1032. stores a string in the string memory and returns a reference to it which can
  1033. be used as attribute of the token
  1034. .i TokString.
  1035. .bp
  1036. .sh 1 Ada
  1037. .pp
  1038. .sh 2 Identifiers
  1039. .lp
  1040. Problems to solve:
  1041. .ip -
  1042. normalization of upper-case and lower-case letters
  1043. .lp
  1044. .(b L
  1045. Solution:
  1046. .sp 0.5
  1047. .FT
  1048. EXPORT  {
  1049. # include "Idents.h"
  1050. # include "Positions.h"
  1051. typedef struct {
  1052.    tPosition Position;
  1053.    tIdent    Ident;
  1054. } tScanAttribute;
  1055. extern void ErrorAttribute ();
  1056. }
  1057.  
  1058. GLOBAL  {
  1059. # define TokIdentifier ...
  1060. void ErrorAttribute (Token, Attribute) ...
  1061. }
  1062.  
  1063. LOCAL   {char String [256]; int L;}
  1064.  
  1065. DEFINE  letter  = {A-Z a-z}.
  1066.         digit   = {0-9}.
  1067.  
  1068. RULE
  1069.  
  1070. letter (_? (letter | digit)+ )* : {L = GetLower (String);
  1071.                 Attribute.Ident = MakeIdent (String, L); return TokIdentifier;}
  1072. .)b
  1073. .pp
  1074. Normalization of upper-case and lower-case letters to lower-case is done by the
  1075. predefined operation
  1076. .i GetLower
  1077. of Rex.
  1078. .bp
  1079. .sh 2 "Numeric Literals"
  1080. .lp
  1081. Problems to solve:
  1082. .ip -
  1083. conversion
  1084. .lp
  1085. .(b L
  1086. Solution:
  1087. .sp 0.5
  1088. .FT
  1089. EXPORT  {
  1090. # include "StringMem.h"
  1091. # include "Positions.h"
  1092. typedef struct {
  1093.    tPosition  Position;
  1094.    tStringRef StringRef;
  1095. } tScanAttribute;
  1096. extern void ErrorAttribute ();
  1097. }
  1098.  
  1099. GLOBAL  {
  1100. # define TokDecimalLiteral ...
  1101. # define TokBasedLiteral ...
  1102. void ErrorAttribute (Token, Attribute) ...
  1103. }
  1104.  
  1105. DEFINE  digit           = {0-9}                 .
  1106.         extended_digit  = digit | {A-F a-f}     .
  1107.         integer         = digit (_? digit) *    .
  1108.         based_integer   = extended_digit (_? extended_digit) *  .
  1109.         exponent        = {Ee} {+\\\\-} ? integer .
  1110.  
  1111. RULE
  1112.  
  1113. integer ("." integer) ? exponent ? :
  1114.                 {Attribute.StringRef = PutString (TokenPtr, TokenLength);
  1115.                  return TokDecimalLiteral;}
  1116.  
  1117. integer "#" based_integer ("." based_integer) ? "#" exponent ? :
  1118.                 {Attribute.StringRef = PutString (TokenPtr, TokenLength);
  1119.                  return TokBasedLiteral;}
  1120. .)b
  1121. .pp
  1122. The conversion of numeric literals to numeric values is not really solved in
  1123. the above solution. By storing the external representation of numeric
  1124. literals in a string memory the values are treated symbolically and true
  1125. conversion is delayed to be done by other compiler phases.
  1126. .bp
  1127. .sh 2 "Character Literals"
  1128. .lp
  1129. Problems to solve:
  1130. .ip -
  1131. no problems to solve for character literals
  1132. .ip -
  1133. distinction between character literals and apostrophes
  1134. .lp
  1135. .(b L
  1136. Solution:
  1137. .sp 0.5
  1138. .FT
  1139. EXPORT  {
  1140. # include "Idents.h"
  1141. # include "Positions.h"
  1142. typedef struct {
  1143.    tPosition Position;
  1144.    char      Char;
  1145.    tIdent    Ident;
  1146. } tScanAttribute;
  1147. extern void ErrorAttribute ();
  1148. }
  1149.  
  1150. GLOBAL  {
  1151. # define TokIdentifier          ...
  1152. # define TokCharacterLiteral    ...
  1153. # define TokApostrophe          ...
  1154. # define TokLParenthesis        ...
  1155. # define TokRParenthesis        ...
  1156. void ErrorAttribute (Token, Attribute) ...
  1157. }
  1158.  
  1159. LOCAL   {char String [256]; int L;}
  1160.  
  1161. DEFINE  character = {\\\\ -~}.
  1162.         letter    = {A-Z a-z}.
  1163.         digit     = {0-9}.
  1164.  
  1165. START   QUOTE
  1166.  
  1167. RULE
  1168.  
  1169. #STD#   ' character '   : {Attribute.Char = TokenPtr [1];
  1170.                            return TokCharacterLiteral;}
  1171. #QUOTE# '               : {yyStart (STD); return TokApostrophe;}
  1172.         "("             : {yyStart (STD); return TokLParenthesis;}
  1173.         ")"             : {yyStart (QUOTE); return TokRParenthesis;}
  1174.         letter (_? (letter | digit)+ )*
  1175.                         : {yyStart (QUOTE); L = GetLower (Word);
  1176.                            Attribute.Ident = MakeIdent (Word, L);
  1177.                            return TokIdentifier;}
  1178. .)b
  1179. .pp
  1180. The tokens
  1181. .i "Character Literal"
  1182. and
  1183. .i Apostrophe
  1184. can be distinguished in Ada only by consideration of some context. The
  1185. pathological input is for example something like
  1186. .lp
  1187. .(b
  1188. .FT
  1189. t'('a','b','c')
  1190. .)b
  1191. where t is a type_mark used as qualification for an aggregate of character
  1192. literals. It has to be taken care that 'a', 'b', and 'c' are recognized as
  1193. character literals and not '(', ',', and ','. Studying the Ada grammar one
  1194. can see that apostrophes are used following identifiers and closing
  1195. parentheses only. There are never character literals in this places.
  1196. .pp
  1197. This leads to the above solution with an additional start state called
  1198. .i QUOTE.
  1199. After recognition of an identifier or a closing parentheses the scanner is
  1200. switched to start state
  1201. .i QUOTE.
  1202. After recognition of all other tokens the scanner is switched back 
  1203. to start state
  1204. .i STD.
  1205. Apostrophes are recognized only in start state
  1206. .i QUOTE
  1207. and character literals only in start state
  1208. .i STD.
  1209. All the other tokens are recognized in both start states.
  1210. .\" bp
  1211. .sh 2 "String Literals"
  1212. .lp
  1213. Problems to solve:
  1214. .ip -
  1215. conversion
  1216. .ip -
  1217. doubled delimiters
  1218. .ip -
  1219. unclosed strings (at end of lines)
  1220. .ip -
  1221. source position
  1222. .lp
  1223. .(b L
  1224. Solution:
  1225. .sp 0.5
  1226. .FT
  1227. EXPORT  {
  1228. # include "StringMem.h"
  1229. # include "Positions.h"
  1230. typedef struct {
  1231.    tPosition  Position;
  1232.    tStringRef StringRef;
  1233. } tScanAttribute;
  1234. extern void ErrorAttribute ();
  1235. }
  1236.  
  1237. GLOBAL  {
  1238. # define TokStringLiteral ...
  1239. void ErrorAttribute (Token, Attribute) ...
  1240. }
  1241.  
  1242. LOCAL   {char String [256]; int L;}
  1243.  
  1244. DEFINE  StrCh   = {\\\\ !#-~}.
  1245.  
  1246. START   string
  1247.  
  1248. RULE
  1249.  
  1250. #STD#    \\\\"     :  {yyStart (string); L = 0;}
  1251. #string# StrCh+ :- {L += GetWord (& String [L]);}
  1252. #string# \\\\"\\\\"   :- {String [L ++] = '\\\\"');}
  1253. #string# \\\\"     :- {yyStart (STD); String [L] = '\\\\0';
  1254.                     Attribute.StringRef = PutString (String, L);
  1255.                     return TokStringLiteral;}
  1256. #string# \\\\n     :- {Error ("unclosed string"); yyEol (0);
  1257.                     yyStart (STD); String [L] = '\\\\0';
  1258.                     Attribute.StringRef = PutString (String, L);
  1259.                     return TokStringLiteral;}
  1260. .)b
  1261. .pp
  1262. We presuppose the existence of a string memory module
  1263. .i StringMem.
  1264. The procedure
  1265. .i PutString
  1266. stores a string in the string memory and returns a reference to it which can
  1267. be used as attribute of the token
  1268. .i TokString.
  1269. .bp
  1270. .sh 2 "Keywords"
  1271. .lp
  1272. Problems to solve:
  1273. .ip -
  1274. normalization of upper-case and lower-case letters
  1275. .lp
  1276. .(b L
  1277. Solution:
  1278. .sp 0.5
  1279. .FT
  1280. GLOBAL  {
  1281. # define TokABORT       ...
  1282.    ...
  1283. # define TokXOR         ...
  1284. void ErrorAttribute (Token, Attribute) ...
  1285. }
  1286.  
  1287. DEFINE  A = {Aa}.
  1288.           ...
  1289.         Z = {Zz}.
  1290.  
  1291. RULE
  1292.  
  1293. A B O R T       : {return TokABORT     ;}
  1294.   ...
  1295. X O R           : {return TokXOR       ;}
  1296. .)b
  1297. .pp
  1298. The idea of the solution is to define identifiers A to Z to stand for the
  1299. corresponding upper-case as well as lower-case letters. Then specifying the
  1300. keywords in upper-case and spaced does the job.
  1301. .bp
  1302. .uh "Appendix: Complete Scanner Specification for Ada"
  1303. .sp
  1304. .lp
  1305. .nf
  1306. .FT
  1307. .sz 10
  1308. GLOBAL  {
  1309.    FROM Strings         IMPORT tString, AssignEmpty, Concatenate, Append, Char;
  1310.    FROM StringMem       IMPORT tStringRef, PutString;
  1311.    FROM Idents          IMPORT tIdent, MakeIdent;
  1312.  
  1313.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  1314.       BEGIN END ErrorAttribute;
  1315.  
  1316. CONST
  1317.    TokIdentifier        =  1    ;
  1318.    TokDecimalLiteral    =  2    ;
  1319.    TokBasedLiteral      =  3    ;
  1320.    TokCharLiteral       =  4    ;
  1321.    TokStringLiteral     =  5    ;
  1322.  
  1323.    TokArrow             =  6    ;       (* '=>'         *)
  1324.    TokDoubleDot         =  7    ;       (* '..'         *)
  1325.    TokDoubleStar        =  8    ;       (* '**'         *)
  1326.    TokBecomes           =  9    ;       (* ':='         *)
  1327.    TokNotEqual          = 10    ;       (* '/='         *)
  1328.    TokGreaterEqual      = 11    ;       (* '>='         *)
  1329.    TokLessEqual         = 12    ;       (* '<='         *)
  1330.    TokLLabelBracket     = 13    ;       (* '<<'         *)
  1331.    TokRLabelBracket     = 14    ;       (* '>>'         *)
  1332.    TokBox               = 15    ;       (* '<>'         *)
  1333.  
  1334.    TokAmpersand         = 16    ;       (* '&'          *)
  1335.    TokApostrophe        = 17    ;       (* '''          *)
  1336.    TokLParenthesis      = 18    ;       (* '('          *)
  1337.    TokRParenthesis      = 19    ;       (* ')'          *)
  1338.    TokStar              = 20    ;       (* '*'          *)
  1339.    TokPlus              = 21    ;       (* '+'          *)
  1340.    TokComma             = 22    ;       (* ','          *)
  1341.    TokMinus             = 23    ;       (* '-'          *)
  1342.    TokDot               = 24    ;       (* '.'          *)
  1343.    TokDivide            = 25    ;       (* '/'          *)
  1344.    TokColon             = 26    ;       (* ':'          *)
  1345.    TokSemicolon         = 27    ;       (* ';'          *)
  1346.    TokLess              = 28    ;       (* '<'          *)
  1347.    TokEqual             = 29    ;       (* '='          *)
  1348.    TokGreater           = 30    ;       (* '>'          *)
  1349.    TokBar               = 31    ;       (* '|'          *)
  1350.  
  1351.    TokABORT             = 32    ;       (* ABORT        *)
  1352.    TokABS               = 33    ;       (* ABS          *)
  1353.    TokACCEPT            = 34    ;       (* ACCEPT       *)
  1354.    TokACCESS            = 35    ;       (* ACCESS       *)
  1355.    TokALL               = 36    ;       (* ALL          *)
  1356.    TokAND               = 37    ;       (* AND          *)
  1357.    TokARRAY             = 38    ;       (* ARRAY        *)
  1358.    TokAT                = 39    ;       (* AT           *)
  1359.    TokBEGIN             = 40    ;       (* BEGIN        *)
  1360.    TokBODY              = 41    ;       (* BODY         *)
  1361.    TokCASE              = 42    ;       (* CASE         *)
  1362.    TokCONSTANT          = 43    ;       (* CONSTANT     *)
  1363.    TokDECLARE           = 44    ;       (* DECLARE      *)
  1364.    TokDELAY             = 45    ;       (* DELAY        *)
  1365.    TokDELTA             = 46    ;       (* DELTA        *)
  1366.    TokDIGITS            = 47    ;       (* DIGITS       *)
  1367.    TokDO                = 48    ;       (* DO           *)
  1368.    TokELSE              = 49    ;       (* ELSE         *)
  1369.    TokELSIF             = 50    ;       (* ELSIF        *)
  1370.    TokEND               = 51    ;       (* END          *)
  1371.    TokENTRY             = 52    ;       (* ENTRY        *)
  1372.    TokEXCEPTION         = 53    ;       (* EXCEPTION    *)
  1373.    TokEXIT              = 54    ;       (* EXIT         *)
  1374.    TokFOR               = 55    ;       (* FOR          *)
  1375.    TokFUNCTION          = 56    ;       (* FUNCTION     *)
  1376.    TokGENERIC           = 57    ;       (* GENERIC      *)
  1377.    TokGOTO              = 58    ;       (* GOTO         *)
  1378.    TokIF                = 59    ;       (* IF           *)
  1379.    TokIN                = 60    ;       (* IN           *)
  1380.    TokIS                = 61    ;       (* IS           *)
  1381.    TokLIMITED           = 62    ;       (* LIMITED      *)
  1382.    TokLOOP              = 63    ;       (* LOOP         *)
  1383.    TokMOD               = 64    ;       (* MOD          *)
  1384.    TokNEW               = 65    ;       (* NEW          *)
  1385.    TokNOT               = 66    ;       (* NOT          *)
  1386.    TokNULL              = 67    ;       (* NULL         *)
  1387.    TokOF                = 68    ;       (* OF           *)
  1388.    TokOR                = 69    ;       (* OR           *)
  1389.    TokOTHERS            = 70    ;       (* OTHERS       *)
  1390.    TokOUT               = 71    ;       (* OUT          *)
  1391.    TokPACKAGE           = 72    ;       (* PACKAGE      *)
  1392.    TokPRAGMA            = 73    ;       (* PRAGMA       *)
  1393.    TokPRIVATE           = 74    ;       (* PRIVATE      *)
  1394.    TokPROCEDURE         = 75    ;       (* PROCEDURE    *)
  1395.    TokRAISE             = 76    ;       (* RAISE        *)
  1396.    TokRANGE             = 77    ;       (* RANGE        *)
  1397.    TokRECORD            = 78    ;       (* RECORD       *)
  1398.    TokREM               = 79    ;       (* REM          *)
  1399.    TokRENAMES           = 80    ;       (* RENAMES      *)
  1400.    TokRETURN            = 81    ;       (* RETURN       *)
  1401.    TokREVERSE           = 82    ;       (* REVERSE      *)
  1402.    TokSELECT            = 83    ;       (* SELECT       *)
  1403.    TokSEPARATE          = 84    ;       (* SEPARATE     *)
  1404.    TokSUBTYPE           = 85    ;       (* SUBTYPE      *)
  1405.    TokTASK              = 86    ;       (* TASK         *)
  1406.    TokTERMINATE         = 87    ;       (* TERMINATE    *)
  1407.    TokTHEN              = 88    ;       (* THEN         *)
  1408.    TokTYPE              = 89    ;       (* TYPE         *)
  1409.    TokUSE               = 90    ;       (* USE          *)
  1410.    TokWHEN              = 91    ;       (* WHEN         *)
  1411.    TokWHILE             = 92    ;       (* WHILE        *)
  1412.    TokWITH              = 93    ;       (* WITH         *)
  1413.    TokXOR               = 94    ;       (* XOR          *)
  1414. }
  1415.  
  1416. LOCAL   {
  1417.    VAR
  1418.       String, S : tString       ;
  1419.       Word      : tString       ;
  1420.       ident     : tIdent        ;
  1421.       string    : tStringRef    ;
  1422.       ch        : CHAR          ;
  1423. }
  1424.  
  1425. DEFINE
  1426.    digit          = {0-9}               .
  1427.    extended_digit = digit | {A-F a-f}   .
  1428.    letter         = {a-z A-Z}           .
  1429.    character      = {\\ -~}              .
  1430.    stringch       = {\\ !#-~}            .
  1431.    integer        = digit (_? digit) *  .
  1432.    based_integer  = extended_digit (_? extended_digit) *  .
  1433.    illegal        = - {\\ \\t\\n}          .
  1434.  
  1435.    A            = {Aa}  .
  1436.    B            = {Bb}  .
  1437.    C            = {Cc}  .
  1438.    D            = {Dd}  .
  1439.    E            = {Ee}  .
  1440.    F            = {Ff}  .
  1441.    G            = {Gg}  .
  1442.    H            = {Hh}  .
  1443.    I            = {Ii}  .
  1444.    J            = {Jj}  .
  1445.    K            = {Kk}  .
  1446.    L            = {Ll}  .
  1447.    M            = {Mm}  .
  1448.    N            = {Nn}  .
  1449.    O            = {Oo}  .
  1450.    P            = {Pp}  .
  1451.    Q            = {Qq}  .
  1452.    R            = {Rr}  .
  1453.    S            = {Ss}  .
  1454.    T            = {Tt}  .
  1455.    U            = {Uu}  .
  1456.    V            = {Vv}  .
  1457.    W            = {Ww}  .
  1458.    X            = {Xx}  .
  1459.    Y            = {Yy}  .
  1460.    Z            = {Zz}  .
  1461.  
  1462. START   STRING, QUOTE
  1463.  
  1464. RULE
  1465.  
  1466. NOT #STRING# integer ("." integer) ? (E {+\\-} ? integer) ?
  1467.                         : {yyStart (STD); GetWord (Word);
  1468.                            string := PutString (Word);
  1469.                            RETURN TokDecimalLiteral;}
  1470.  
  1471. NOT #STRING#
  1472.     integer "#" based_integer ("." based_integer) ? "#" (E {+\\-} ? integer) ?
  1473.                         : {yyStart (STD); GetWord (Word);
  1474.                            string := PutString (Word);
  1475.                            RETURN TokBasedLiteral;}
  1476.  
  1477.     #STD#  ' character ': {GetWord (String); ch := Char (String, 2);
  1478.                            RETURN TokCharLiteral;}
  1479.  
  1480. NOT #STRING# \\"         :  {yyStart (STRING); AssignEmpty (String);}
  1481.     #STRING# stringch + :- {GetWord (S); Concatenate (String, S);}
  1482.     #STRING# \\"\\"       :- {Append (String, '"');}
  1483.     #STRING# \\"         :- {yyStart (STD); string := PutString (String);
  1484.                             RETURN TokStringLiteral;}
  1485.     #STRING# \\t         :- {Append (String, 11C); yyTab;}
  1486.     #STRING# \\n         :- {(* Error ("unclosed string"); *) yyEol (0);
  1487.                             yyStart (STD); string := PutString (String);
  1488.                             RETURN TokStringLiteral;}
  1489.  
  1490. NOT #STRING# "--" ANY * : {}
  1491.  
  1492. NOT #STRING# "=>"       : {yyStart (STD); RETURN TokArrow               ;}
  1493. NOT #STRING# ".."       : {yyStart (STD); RETURN TokDoubleDot           ;}
  1494. NOT #STRING# "**"       : {yyStart (STD); RETURN TokDoubleStar          ;}
  1495. NOT #STRING# ":="       : {yyStart (STD); RETURN TokBecomes             ;}
  1496. NOT #STRING# "/="       : {yyStart (STD); RETURN TokNotEqual            ;}
  1497. NOT #STRING# ">="       : {yyStart (STD); RETURN TokGreaterEqual        ;}
  1498. NOT #STRING# "<="       : {yyStart (STD); RETURN TokLessEqual           ;}
  1499. NOT #STRING# "<<"       : {yyStart (STD); RETURN TokLLabelBracket       ;}
  1500. NOT #STRING# ">>"       : {yyStart (STD); RETURN TokRLabelBracket       ;}
  1501. NOT #STRING# "<>"       : {yyStart (STD); RETURN TokBox                 ;}
  1502.  
  1503. NOT #STRING# "&"        : {yyStart (STD); RETURN TokAmpersand           ;}
  1504.     #QUOTE#  "'"        : {yyStart (STD); RETURN TokApostrophe          ;}
  1505. NOT #STRING# "("        : {yyStart (STD); RETURN TokLParenthesis        ;}
  1506. NOT #STRING# ")"        : {yyStart (QUOTE); RETURN TokRParenthesis      ;}
  1507. NOT #STRING# "*"        : {yyStart (STD); RETURN TokStar                ;}
  1508. NOT #STRING# "+"        : {yyStart (STD); RETURN TokPlus                ;}
  1509. NOT #STRING# ","        : {yyStart (STD); RETURN TokComma               ;}
  1510. NOT #STRING# "-"        : {yyStart (STD); RETURN TokMinus               ;}
  1511. NOT #STRING# "."        : {yyStart (STD); RETURN TokDot                 ;}
  1512. NOT #STRING# "/"        : {yyStart (STD); RETURN TokDivide              ;}
  1513. NOT #STRING# ":"        : {yyStart (STD); RETURN TokColon               ;}
  1514. NOT #STRING# ";"        : {yyStart (STD); RETURN TokSemicolon           ;}
  1515. NOT #STRING# "<"        : {yyStart (STD); RETURN TokLess                ;}
  1516. NOT #STRING# "="        : {yyStart (STD); RETURN TokEqual               ;}
  1517. NOT #STRING# ">"        : {yyStart (STD); RETURN TokGreater             ;}
  1518. NOT #STRING# "|"        : {yyStart (STD); RETURN TokBar                 ;}
  1519.  
  1520. NOT #STRING# A B O R T          : {yyStart (STD); RETURN TokABORT       ;}
  1521. NOT #STRING# A B S              : {yyStart (STD); RETURN TokABS         ;}
  1522. NOT #STRING# A C C E P T        : {yyStart (STD); RETURN TokACCEPT      ;}
  1523. NOT #STRING# A C C E S S        : {yyStart (STD); RETURN TokACCESS      ;}
  1524. NOT #STRING# A L L              : {yyStart (STD); RETURN TokALL         ;}
  1525. NOT #STRING# A N D              : {yyStart (STD); RETURN TokAND         ;}
  1526. NOT #STRING# A R R A Y          : {yyStart (STD); RETURN TokARRAY       ;}
  1527. NOT #STRING# A T                : {yyStart (STD); RETURN TokAT          ;}
  1528. NOT #STRING# B E G I N          : {yyStart (STD); RETURN TokBEGIN       ;}
  1529. NOT #STRING# B O D Y            : {yyStart (STD); RETURN TokBODY        ;}
  1530. NOT #STRING# C A S E            : {yyStart (STD); RETURN TokCASE        ;}
  1531. NOT #STRING# C O N S T A N T    : {yyStart (STD); RETURN TokCONSTANT    ;}
  1532. NOT #STRING# D E C L A R E      : {yyStart (STD); RETURN TokDECLARE     ;}
  1533. NOT #STRING# D E L A Y          : {yyStart (STD); RETURN TokDELAY       ;}
  1534. NOT #STRING# D E L T A          : {yyStart (STD); RETURN TokDELTA       ;}
  1535. NOT #STRING# D I G I T S        : {yyStart (STD); RETURN TokDIGITS      ;}
  1536. NOT #STRING# D O                : {yyStart (STD); RETURN TokDO          ;}
  1537. NOT #STRING# E L S E            : {yyStart (STD); RETURN TokELSE        ;}
  1538. NOT #STRING# E L S I F          : {yyStart (STD); RETURN TokELSIF       ;}
  1539. NOT #STRING# E N D              : {yyStart (STD); RETURN TokEND         ;}
  1540. NOT #STRING# E N T R Y          : {yyStart (STD); RETURN TokENTRY       ;}
  1541. NOT #STRING# E X C E P T I O N  : {yyStart (STD); RETURN TokEXCEPTION   ;}
  1542. NOT #STRING# E X I T            : {yyStart (STD); RETURN TokEXIT        ;}
  1543. NOT #STRING# F O R              : {yyStart (STD); RETURN TokFOR         ;}
  1544. NOT #STRING# F U N C T I O N    : {yyStart (STD); RETURN TokFUNCTION    ;}
  1545. NOT #STRING# G E N E R I C      : {yyStart (STD); RETURN TokGENERIC     ;}
  1546. NOT #STRING# G O T O            : {yyStart (STD); RETURN TokGOTO        ;}
  1547. NOT #STRING# I F                : {yyStart (STD); RETURN TokIF          ;}
  1548. NOT #STRING# I N                : {yyStart (STD); RETURN TokIN          ;}
  1549. NOT #STRING# I S                : {yyStart (STD); RETURN TokIS          ;}
  1550. NOT #STRING# L I M I T E D      : {yyStart (STD); RETURN TokLIMITED     ;}
  1551. NOT #STRING# L O O P            : {yyStart (STD); RETURN TokLOOP        ;}
  1552. NOT #STRING# M O D              : {yyStart (STD); RETURN TokMOD         ;}
  1553. NOT #STRING# N E W              : {yyStart (STD); RETURN TokNEW         ;}
  1554. NOT #STRING# N O T              : {yyStart (STD); RETURN TokNOT         ;}
  1555. NOT #STRING# N U L L            : {yyStart (STD); RETURN TokNULL        ;}
  1556. NOT #STRING# O F                : {yyStart (STD); RETURN TokOF          ;}
  1557. NOT #STRING# O R                : {yyStart (STD); RETURN TokOR          ;}
  1558. NOT #STRING# O T H E R S        : {yyStart (STD); RETURN TokOTHERS      ;}
  1559. NOT #STRING# O U T              : {yyStart (STD); RETURN TokOUT         ;}
  1560. NOT #STRING# P A C K A G E      : {yyStart (STD); RETURN TokPACKAGE     ;}
  1561. NOT #STRING# P R A G M A        : {yyStart (STD); RETURN TokPRAGMA      ;}
  1562. NOT #STRING# P R I V A T E      : {yyStart (STD); RETURN TokPRIVATE     ;}
  1563. NOT #STRING# P R O C E D U R E  : {yyStart (STD); RETURN TokPROCEDURE   ;}
  1564. NOT #STRING# R A I S E          : {yyStart (STD); RETURN TokRAISE       ;}
  1565. NOT #STRING# R A N G E          : {yyStart (STD); RETURN TokRANGE       ;}
  1566. NOT #STRING# R E C O R D        : {yyStart (STD); RETURN TokRECORD      ;}
  1567. NOT #STRING# R E M              : {yyStart (STD); RETURN TokREM         ;}
  1568. NOT #STRING# R E N A M E S      : {yyStart (STD); RETURN TokRENAMES     ;}
  1569. NOT #STRING# R E T U R N        : {yyStart (STD); RETURN TokRETURN      ;}
  1570. NOT #STRING# R E V E R S E      : {yyStart (STD); RETURN TokREVERSE     ;}
  1571. NOT #STRING# S E L E C T        : {yyStart (STD); RETURN TokSELECT      ;}
  1572. NOT #STRING# S E P A R A T E    : {yyStart (STD); RETURN TokSEPARATE    ;}
  1573. NOT #STRING# S U B T Y P E      : {yyStart (STD); RETURN TokSUBTYPE     ;}
  1574. NOT #STRING# T A S K            : {yyStart (STD); RETURN TokTASK        ;}
  1575. NOT #STRING# T E R M I N A T E  : {yyStart (STD); RETURN TokTERMINATE   ;}
  1576. NOT #STRING# T H E N            : {yyStart (STD); RETURN TokTHEN        ;}
  1577. NOT #STRING# T Y P E            : {yyStart (STD); RETURN TokTYPE        ;}
  1578. NOT #STRING# U S E              : {yyStart (STD); RETURN TokUSE         ;}
  1579. NOT #STRING# W H E N            : {yyStart (STD); RETURN TokWHEN        ;}
  1580. NOT #STRING# W H I L E          : {yyStart (STD); RETURN TokWHILE       ;}
  1581. NOT #STRING# W I T H            : {yyStart (STD); RETURN TokWITH        ;}
  1582. NOT #STRING# X O R              : {yyStart (STD); RETURN TokXOR         ;}
  1583.  
  1584. NOT #STRING# letter (_? (letter | digit)+ )*
  1585.                                 : {yyStart (QUOTE); GetLower (Word);
  1586.                                    ident := MakeIdent (Word);
  1587.                                    RETURN TokIdentifier;}
  1588.  
  1589. NOT #STRING# illegal            : {IO.WriteS (IO.StdOutput, "illegal character: ");
  1590.                                    yyEcho; IO.WriteNl (IO.StdOutput);}
  1591. .fi
  1592. .sz 12
  1593. .[]
  1594. .[-
  1595. .ds [F Gro87
  1596. .ds [A J\*(p] Grosch
  1597. .ds [T Rex - A Scanner Generator
  1598. .ds [I GMD Forschungsstelle an der Universit\\*:at Karlsruhe
  1599. .ds [R Compiler Generation Report No. 5
  1600. .ds [N 5
  1601. .ds [D Dec. 1987
  1602. .][
  1603. .bp 1
  1604. .lp
  1605. .b Contents
  1606. .sp
  1607. .xp
  1608.